跳到主要内容

状态机

这里指客户端自定义状态机,即客户端单位上的状态机。一个单位可以有多个状态机,这些状态机同时tick, 但是最终只有优先级最高的一个状态机控制单位播动画。 除了服务端状态机同步过来的状态机,客户端还可以额外创建状态机。 客户端状态机有layer和priority属性,服务端状态机没有。 layer控制状态机影响全身(layer=0)、上半身(layer=1)、下半身(layer=2) priority控制状态机的优先级,移动状态机(priority=0)优先级最低,技能状态机(priority=1)比移动状态机优先级高,所以放技能的时候播技能动画,而不是移动动画, 尽管两个状态机都在tick。自定义装状态机的优先级一般设为2或2以上

状态机创建

状态机附属于单位,由单位创建状态机(也可以依赖服务端状态机同步来创建状态机)

get_or_create_state_machine

创建自定义服务端状态机,如果已经存在就返回存在的状态机

  • 参数
    • name (string) - 状态机名字,同一个单位上的状态机名字不能重复。注意不要使用形如"skill"的名字,这些被默认状态机占用了
    • priority (uint) - 优先级
    • layer (uint) - 影响层级,仅取值0(全身),1(上半身),2(下半身)
  • 返回
    • sm (table) - 状态机lua对象
    • new (bool) - 是否是新创建的
local sm, new = unit:get_or_create_state_machine('taunt', 2, 0)

状态机api

get_priority

获取状态机优先级

  • 返回
    • priority (uint)
local priority = sm:get_priority()

add_state

状态机添加状态,如果id已经有了就返回已经有的状态 注意:创建状态机的时候状态机默认创建id为-1, name为'exit'的状态,并且状态机的当前状态为'exit'

  • 参数
    • name (string) - 状态名(只是起描述性作用)
    • id (int) - 状态id
  • 返回
    • state (table) - state的lua对象
local state = sm:add_state('idle', 0)

get_state

根据id获取状态机的状态

  • 参数

    • id (int) - 状态id
  • 返回

    • state (table) - state的lua对象
local exit_state = sm:get_state(-1)

set_current_state

根据id设置状态机的当前状态

  • 参数
    • id (int) - 状态id, 注意id对应的状态必须先添加到状态机,否则不生效
sm:set_current_state(id)

transit

状态机根据event id切换状态。如果是同步给客户端的状态机。服务端切状态了,客户端对应的状态机也会切状态。

  • 参数
    • id (uint8) - 事件id(>=0且<=255), 注意id对应的事件必须先添加到状态转移表里,否则不生效
sm:transit(id)

set_animation_state

状态机设置播放的动画,如果状态机优先级高,在排序中胜出了,模型就会播放。

状态api

get_name

获取状态名

  • 返回
    • name (string)
local name = state:get_name()

get_id

获取状态id

  • 返回
    • id (int)
local state_id = state:get_id()

add_transition

状态添加转移表,即什么事件可以使状态机从当前状态切换到下一个状态

  • 参数
    • id (uint8) - 事件id,可以用enum来封装以明确含义,但是api接收的是uint8
    • next(table)- 下一个状态的lua对象
local idle_state = sm:get_state(0)
local exit_state = sm:get_state(-1)
local event = {idle=0, exit=1}
exit_state:add_transition(event.idle, idle_state)
idle_state:add_transition(event.exit, exit_state)

回调

状态切换的时候会触发回调 回调调用顺序:比如从idle状态切换到walk状态,先调用idle:on_exit(), 再调用walk:on_enter(), 然后每帧调用walk:on_update(delta)

on_enter

进入状态的时候调用

  • 参数
    • self (table) - 状态的lua对象
local idle_state = sm:get_state(0)
function idle_state:on_enter()
log.info('enter idle state')
end

on_update

状态tick的时候调用

  • 参数
    • self (table) - 状态的lua对象
    • delta (float) - 更新的delta时间,单位秒
local idle_state = sm:get_state(0)
function idle_state:on_update(delta)
log.info('update idle state, time elapsed', delta)
end

on_exit

离开状态的时候调用

  • 参数
    • self (table) - 状态的lua对象
local idle_state = sm:get_state(0)
function idle_state:on_exit()
log.info('leave idle state')
end